using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;
using BrainTechLLC;

namespace Mud.EmlenMudMain
{
#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class HelpData : IComparable, IHelpData
    {
        public HelpData() { }

        private int level = -1;			/* Minimum level required to see this helpfile */
        private string keyword = "";	/* KeywordList list that will display the help text */
        private string text = "";		/* Actual help text */
#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        public int nUses = 0;

        public int MinimumLevelToViewTopic
        {
            get { return level; }
            set { level = value; }
        }

        public string KeywordList
        {
            get { return keyword; }
            set { keyword = value; }
        }

        public string HelpText
        {
            get { return text; }
            set { text = value; }
        }

        /// <summary>
        /// The most frequently used help files are near the front of the list :)
        /// No, you don't have to change your help "area" file for this to happen :)
        /// </summary>		
        public int NumberOfUses
        {
            get { return nUses; }
            set { nUses = value; }
        }

        // This allows HelpData to be sorted by use so we quickly find
        // the most commonly-used help topics
        public int CompareTo(object obj)
        {
            if (obj is HelpData) { return nUses.CompareTo(((HelpData)obj).nUses); }
            else return 0;
        }

        #region "Login and common help topics"
        public string AskPasswordText(InterfaceType usingInterface)
        {
            HelpData h = null;
            // The mangled name is so that users don't get this as a help
            // message by accident if they type "help password" or something
            // similar, etc...
            h = HelpData.FindHelpTopic("GPASWTXT", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "GPASWTXT";
                h.HelpText = "Please enter your password: ";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }

        public string InvalidPasswordMessage(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = HelpData.FindHelpTopic("IVLPWDM", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "IVLPWDM";
                h.HelpText = "Invalid Password. Try again: ";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }

        public string WelcomeAndMOTD(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = HelpData.FindHelpTopic("MOTD", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "MOTD";
                h.HelpText = "Welcome!  Press Enter to begin...";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }

        public string ConfirmNewUserMessage(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = HelpData.FindHelpTopic("CONFIRM_IS_NEW_USER_TEXT", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "CONFIRM_IS_NEW_USER_TEXT";
                h.HelpText = "Your player name was not found.  Are you a new user? [Y/N] ";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }

        public string InvalidANSIResponseMessage(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = HelpData.FindHelpTopic("INVALID_ANSI_RESPONSE", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "INVALID_ANSI_RESPONSE";
                h.HelpText = "Invalid response.  Try again [Y/N] ";
                HelpData.AddHelpTopic(h);
            }

            return h.HelpText;
        }

        public string MenuText(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = HelpData.FindHelpTopic("PRELOGIN_MENU", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "PRELOGIN_MENU";
                h.HelpText = "\n\r\n\r -= Main Pre-Login Menu =-\n\r\n\r" +
              " 1) Enter the game.\n\r" +
              " 2) View your character 'score'.\n\r" +
              " 3) View your character's 'attributes'.\n\r" +
              " 4) Read the Background Story.\n\r" +
              " 5) See recent game changes.\n\r" +
              " 6) View the 'who' list.\n\r" +
              " 7) Disconnect [Leave the game].\n\r" +
              "\n\rEnter your selection: ";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }


        public string GreetingMessage(InterfaceType usingInterface)
        {
            HelpData h = null;
            h = (usingInterface == InterfaceType.ANSI) ?
                HelpData.FindHelpTopic("GREETING", 1) :
                HelpData.FindHelpTopic("GREETING_RAW", 1);

            if (h == null)
            {
                h = new HelpData();
                h.MinimumLevelToViewTopic = 0;
                h.KeywordList = "GREETING";
                h.HelpText = "<div align=center>{G}-= MPV =-\n\r" +
                       "{B}[Multi-User Game System Midpoint Void]\n\r" +
                       "{C}Major Code Revision version 5.0\n\r" +
                       "{Y}Implementors: <a target=_blank href=http://www.braintechllc.com/owen.aspx>Owen Emlen</a>, others to come...\r\n\r\n" +
                       "----------------------------------------------------------------\n\r" +
                       "Thanks to everyone who helped carry on the drama (err.. legacy)\n\r" +
                       "System rewrite (C# .NET 2.0), by Owen Emlen, , and , 12/25/06\n\r" +
                       "----------------------------------------------------------------\n\r" +
                       "DIKU Team: K.Nyboe, T.Madsen, H.Staerfeldt, M.Seifert, S.Hammer\n\r" +
                       "Mortal Conquest Base Code by: Owen Emlen, Simon Lee, Dan Biegal.\n\r" +
                       "OLC base code from TheIsles v1.0 by Locke.\n\r" +
                       "----------------------------------------------------------------</div>\n\r" +
                       "{W}By what name do you wish to be called? ";
                HelpData.AddHelpTopic(h);
            }

            return StringLib.add_color(usingInterface, h.HelpText, false).ToString();
        }
        #endregion

        public static bool LoadAllHelpTopics(int inVersion)
        {
            return HelpData.SerializeIn(inVersion);
        }

        public static bool SaveAllHelpTopics(int outVersion)
        {
            return HelpData.SerializeOut(outVersion);
        }

        public static bool SerializeIn(int inVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(HelpData).Name.ToString() + inVersion.ToString();
            Object o = SerializationHelper.SerializeObjectIn(szFName);
            if (o == null) return false;
            if (o is ArrayList)
            {
                ArrayList rghelp = (ArrayList)o;
                for (int i = 0; i < rghelp.Count; i++)
                {
                    HelpData hlp = (HelpData)rghelp[i];
                    //hlp.AssignEmlenMud(EmlenMud);
                    HelpData.AddHelpTopic(hlp);
                }
                return true;
            }
            return false;
#else 
            return true;
#endif
        }

        public static bool SerializeOut(int outVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(HelpData).Name.ToString() + outVersion.ToString();
            return SerializationHelper.SerializeObjectOut(EmlenMud.WorldTemplates.AllHelpTopics, szFName, true);
#else 
            return true;
#endif
        }


        public static bool AddHelpTopic(HelpData help)
        {
            // if (help.EmlenMud == null) help.AssignEmlenMud();
            help.keyword = help.keyword.ToUpper();
            for (int n = 0; n < EmlenMud.WorldTemplates.AllHelpTopics.Count; n++)
            {
                HelpData h = (HelpData)EmlenMud.WorldTemplates.AllHelpTopics[n];
                if (h.level == help.level && h.keyword == help.keyword)
                    return false;
            }

            // TODO EmlenMud.WorldTemplates.AllHelpTopics.Add(help);
            return true;
        }

        public static HelpData FindHelpTopic(string sz, int charlevel)
        {
            if (sz == null) return null;
            if (sz.Length < 2) return null;
            string szSeek = sz.ToUpper();

            string[] rgSearchFor = szSeek.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            for (int n = 0; n < EmlenMud.WorldTemplates.AllHelpTopics.Count; n++)
            {
                HelpData h = (HelpData)EmlenMud.WorldTemplates.AllHelpTopics[n];
                bool fTermMatch = false;
                for (int i = 0; i < rgSearchFor.Length; i++)
                {
                    string szTerm = rgSearchFor[i];
                    int nIndexFound = h.keyword.IndexOf(szTerm, StringComparison.Ordinal);
                    if (nIndexFound < 0) { fTermMatch = false; break; }
                    else if (nIndexFound == 0 && h.keyword.Equals(szTerm, StringComparison.Ordinal) == true) { fTermMatch = true; }
                    else if (nIndexFound == 0 && h.keyword.StartsWith(szTerm + " ", StringComparison.Ordinal) == true) { fTermMatch = true; }
                    else if (nIndexFound > 0 && h.keyword.EndsWith(szTerm, StringComparison.Ordinal) == true &&
                         h.keyword[nIndexFound - 1] == ' ') { fTermMatch = true; }
                    else if (nIndexFound > 0 && h.keyword[nIndexFound - 1] == ' ' &&
                                ((nIndexFound + szTerm.Length) < (h.keyword.Length - 1)))
                    {
                        if (h.keyword[nIndexFound + 1] == ' ') { fTermMatch = true; }
                    }
                }
                if (fTermMatch == true) { h.nUses++; return h; }
            }

            for (int n = 0; n < EmlenMud.WorldTemplates.AllHelpTopics.Count; n++)
            {
                HelpData h = (HelpData)EmlenMud.WorldTemplates.AllHelpTopics[n];
                if (h.level > charlevel) continue;
                if (h.keyword.StartsWith(szSeek, StringComparison.Ordinal) == true)
                {
                    h.nUses++;
                    return h;
                }
            }

            for (int n = 0; n < EmlenMud.WorldTemplates.AllHelpTopics.Count; n++)
            {
                HelpData h = (HelpData)EmlenMud.WorldTemplates.AllHelpTopics[n];
                if (h.level > charlevel) continue;
                if (h.keyword.IndexOf(szSeek, StringComparison.Ordinal) >= 0)
                {
                    h.nUses++;
                    return h;
                }
            }

            return null;
        }

        /// <summary>
        /// Nasty, nasty old code below, but it pulls in the old files
        /// </summary>
        /// <param name="sr"></param>
        public static void load_old_style_helps(StreamReader sr)
        {            
            char[] spc = " ".ToCharArray();
            StringBuilder sb = new StringBuilder(4096);

            while (sr.EndOfStream == false)
            {
                string szHelpLine = "";
                while (szHelpLine == "" || szHelpLine.Length <= 1) szHelpLine = sr.ReadLine().Trim();
                string[] rgsz = szHelpLine.Split(spc, 2, StringSplitOptions.RemoveEmptyEntries);
                HelpData pHelp = new HelpData();
                pHelp.level = Convert.ToInt32(rgsz[0]);
                pHelp.keyword = rgsz[1].TrimEnd('~').ToUpper();
                pHelp.keyword = pHelp.keyword.Replace("'", "");
                pHelp.keyword = pHelp.keyword.Replace("\"", "");

                if (pHelp.keyword[0] == '$')
                    break;

                sb.Length = 0;
                string szL2 = sr.ReadLine();
                while (szL2.Trim() != "~" && szL2.Trim().EndsWith("~") == false)
                {
                    sb.AppendLine(szL2);
                    szL2 = sr.ReadLine();
                }
                pHelp.text = sb.ToString();
                AddHelpTopic(pHelp);
            }
        }
    }
}

// OLD CODE to PORT:

//void 
//do_commands (CharacterData  chr, string szUserArguments)
//{
//  int h;
//  COMMAND *c;
//  int sz = 0;
//  char tt[STD_LENGTH];
//  char arg[STD_LENGTH];
//  int col = 1;
//  int minLevelToJoin = -1;
//  int maxlev = 110;

//  DEFINE_COMMAND ("commands", do_commands, POSITION_DEAD, 0, NORMAL, "Help on commands, or a command list.")
//    szUserArguments = one_argy (szUserArguments, arg);
//  if (is_number (arg))
//    {
//      minLevelToJoin = atoi (arg);
//    }
//  if (szUserArguments[0] == '\0' && !is_number (arg))
//    szUserArguments = arg;
//  else if (is_number (szUserArguments))
//    {
//      maxlev = atoi (szUserArguments);
//      szUserArguments[0] = '\0';
//    }
//  hugebuf_o[0] = '\0';

//  if (szUserArguments[0] == '\0')
//    {
//      for (h = 0; h < 256; h++)
//   {
//     for (c = command_hash[h]; c != NULL; c = c->next)
//       {
//         if (LEVEL (chr) < c->level)
//      continue;
//         if (c->level < minLevelToJoin)
//      continue;
//         if (c->level > maxlev)
//      continue;
//         if (col == 4)
//      {
//        col = 1;
//        sprintf (hugebuf_o + sz, "\n\r");
//        sz += 2;
//      }
//         sprintf (tt, "%-20s", c->name);
//         sprintf (hugebuf_o + sz, "%s", tt);
//         sz += (int) strlen (tt);
//         col++;
//       }
//   }
//      sprintf (hugebuf_o + sz, "\n\r");
//      page_to_char (hugebuf_o, chr);
//      return;
//    }

//  for (c = command_hash[UPPER (szUserArguments[0])]; c != NULL; c = c->next)
//    {
//      if (LEVEL (chr) < c->level)
//   continue;
//      if (!str_prefix (szUserArguments, c->name))
//   {
//     int pp = chr->position;
//     chr->position = POSITION_STANDING;
//     sprintf (tt, "\x1B[32;1m\"%s\"\x1B[34;1m\n\r", c->name);
//     send_to_char (tt, chr);
//     send_to_char ("------------------------------------------------------------------------------\x1B[37;1m\n\r", chr);
//     sprintf (tt, "%s", c->help);
//     currentActionsAndBehavior (tt, chr, NULL, chr, TO_CHAR);
//     send_to_char ("\x1B[34;1m------------------------------------------------------------------------------\x1B[37;0m\n\r", chr);
//     chr->position = pp;
//     return;
//   }
//    }

//  send_to_char ("Command not found.\n\r", chr);
//  return;
//}

//void 
//do_socials (CharacterData  chr, string szUserArguments)
//{
//  char buf[STD_LENGTH];
////  int iSocial;
//  SOCIAL *s;
//  int col;
//  DEFINE_COMMAND ("socials", do_socials, POSITION_DEAD, 0, NORMAL, "This command shows all socials currently in the database.")

//    col = 0;
//  for (s = social_list; s != NULL; s = s->next)
//    {
///*for ( iSocial = 0; social_table[iSocial].name[0] != '\0'; iSocial++ ) { */
//      sprintf (buf, "%-12s", s->name);
//      send_to_char (buf, chr);
//      if (++col % 6 == 0)
//   send_to_char ("\n\r", chr);
//    }

//  if (col % 6 != 0)
//    send_to_char ("\n\r", chr);
//  return;
//}
